var kissPage =
{
	goIncognito: function()
	{
		chrome.windows.create({"incognito": true});
	}
};

var systemCommands = 
{
	"bookmarks": {"id": "bookmarks", "name": "Bookmarks", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://bookmarks/", "icons": [{"size": 48, "url": "themes/Faenza/bookmarks.png"}]},
	"history": {"id": "history", "name": "History", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://history/", "icons": [{"size": 48, "url": "themes/Faenza/history.png"}]},
	"downloads": {"id": "downloads", "name": "Downloads", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://downloads/", "icons": [{"size": 48, "url": "themes/Faenza/downloads.png"}]},
	"extensions": {"id": "extensions", "name": "Extensions", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://extensions/", "icons": [{"size": 48, "url": "themes/Faenza/extensions.png"}]},
	"appOptions": {"id": "appOptions", "name": "KISSpage Options", "enabled": true, "isApp": false, "isSystem": false, "url": "options.html", "icons": [{"size": 48, "url": "themes/Faenza/appoptions.png"}]},
	"options": {"id": "options", "name": "Chrome Options", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://settings/", "icons": [{"size": 48, "url": "themes/Faenza/settings.png"}]},
	"clearBrowserData": {"id": "clearBrowserData", "name": "Clear Data", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://settings/clearBrowserData", "icons": [{"size": 48, "url": "themes/Faenza/cleardata.png"}]},
	"contentSettings": {"id": "contentSettings", "name": "Content Settings", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://settings/content", "icons": [{"size": 48, "url": "themes/Faenza/contentsettings.png"}]},
	"incognito": {"id": "incognito", "name": "Incognito", "enabled": true, "isApp": false, "isSystem": false, "url": "javascript:kissPage.goIncognito()", "icons": [{"size": 48, "url": "themes/Faenza/incognito.png"}]},
	"plugins": {"id": "plugins", "name": "Plug-ins", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://plugins/", "icons": [{"size": 48, "url": "themes/Faenza/plugins.png"}]},
	"stats": {"id": "stats", "name": "Stats", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://memory/", "icons": [{"size": 48, "url": "themes/Faenza/stats.png"}]},
	"experimental": {"id": "experimental", "name": "Experimental", "enabled": true, "isApp": false, "isSystem": true, "url": "chrome://flags/", "icons": [{"size": 48, "url": "themes/Faenza/experimental.png"}]}
};

var webStore = {"id": "webStore", "name": "Web Store", "enabled": true, "isApp": true, "isSystem": false, "appLaunchUrl": "https://chrome.google.com/webstore", "icons": [{"size": 48, "url": "themes/Faenza/webstore.png"}]};

$.template("container", "<fieldset class=\"container\" data-id=\"${id}\"><legend>${title}</legend><div class=\"area\"></div></fieldset>");
$.template("item", "<a class=\"item\" href=\"${url}\" title=\"${name}\" data-id=\"${id}\"><div class=\"insertionPoint\"></div><div class=\"icon\"></div><label>${name}</label></a>");
$.template("rawHtml", "<div class=\"rawHtml\"></div>");

$.template("containerEditor", "																				\
	<div class=\"editor\">																					\
		<div class=\"field\">																				\
			<label for=\"${id}_edit_title\">Title</label>													\
			<input type=\"text\" id=\"${id}_edit_title\" class=\"title value\" />							\
		</div>																								\
		<div class=\"field\">																				\
			<label for=\"${id}_edit_size\">Size</label>														\
			<select id=\"${id}_edit_size\" class=\"size value\" title=\"${size}\">							\
				<option value=\"16\">Small (16 x 16)</option>												\
				<option value=\"48\">Medium (48 x 48)</option>												\
				<option value=\"128\">Large (128 x 128)</option>											\
			</select>																						\
		</div>																								\
		<div class=\"checkbox field\">																		\
			<input type=\"checkbox\" id=\"${id}_edit_labels\" value=\"noLabels\" class=\"classes value\" />	\
			<label for=\"${id}_edit_labels\">Hide Labels</label>											\
		</div>																								\
	</div>																									\
	");

var options =
{
	_default: {
		containers: [
			{"id": "default1", "title": "System", "size": 48, "classes": "floatLeft",
				"items": [systemCommands.bookmarks, systemCommands.history, systemCommands.downloads]},
			{"id": "default2", "title": "Options", "size": 48, "classes": "floatLeft",
				"items": [systemCommands.options, systemCommands.extensions, systemCommands.appOptions]},
			{"id": "default3", "title": "Privacy", "size": 48, "classes": "floatRight",
				"items": [systemCommands.clearBrowserData, systemCommands.contentSettings, systemCommands.incognito]},
			{"id": "default4", "title": "Apps", "size": 48, "classes": "noLabels",
				"items": [webStore, {"specialType": "appsExcept"}]}
		],
		getContainerIndex: function(id)
		{
			var opt = options.get();
			
			for (var i = 0; i < opt.containers.length; i++)
			{
				var current = opt.containers[i];
				if (typeof id !== "undefined" && current.id === id.toString())
					return i;
			}
			
			return -1;
		}
	},
	detectUpgrade: function()
	{
		$.getJSON(chrome.extension.getURL("manifest.json"), function(e) {
			if (!localStorage.version)
				window.open(chrome.extension.getURL("options.html?install#release"));
			else if (localStorage.version !== e.version)
				window.open(chrome.extension.getURL("options.html?upgrade#release"));
			else
				return;
			localStorage.version = e.version;
		});
	},
	displayVersion: function(elem)
	{
		$.getJSON(chrome.extension.getURL("manifest.json"), function(e) {
			$(elem).text(e.version);
		});
	},
	get: function()
	{
		options.detectUpgrade();
		var opt = null;
		if (localStorage.options)
			opt = JSON.parse(localStorage.options);
		if (!opt)
			opt = { };
		
		for (var o in options._default)
		{
			if (!opt[o])
				opt[o] = options._default[o];
		}
		
		return opt;
	},
	clear: function()
	{
		localStorage.removeItem("options");
	},
	removeItem: function(containerId, itemId)
	{
		var removed = false;
		var opt = options.get();
		var index = opt.getContainerIndex(containerId);
		if (index < 0)
			return removed;
		
		var container = opt.containers[index];
		for (var i = 0; i < container.length; i++)
		{
			if (container[i].id === itemId)
			{
				container.items = Array.prototype.splice.call(container.items, i, 1);
				removed = true;
			}
		}
		
		if (removed)
			localStorage.options = JSON.stringify(opt);
		
		return removed;
	},
	set: function(optionsFunction)
	{
		var opt = options.get();
		var args = Array.prototype.slice.call(arguments, 1);
		var result = optionsFunction.apply(opt, args);
		localStorage.options = JSON.stringify(opt);
		return result;
	},
	setContainer: function(id, containerFunction)
	{
		var opt = options.get();
		var index = opt.getContainerIndex(id);
		var con;
		if (index < 0)
		{
			if (id instanceof Container)
				con = id.data();
			else
				con = new Container();
		}
		else
		{
			con = opt.containers[index];
		}
		
		if (containerFunction)
		{
			var args = Array.prototype.slice.call(arguments, 2);
			var result = containerFunction.apply(con, args);
		}
		
		if (index < 0)
			opt.containers.push(con);
		else
			opt.containers[index] = con;

		localStorage.options = JSON.stringify(opt);
		return result;
	},
	setContainerOrder: function(order)
	{
		var opt = options.get();
		var con = [];
		
		for (var i = 0; i < order.length; i++)
		{
			var index = opt.getContainerIndex(order[i]);
			if (index >= 0)
				con.push(opt.containers[index]);
		}

		opt.containers = con;
		localStorage.options = JSON.stringify(opt);
	},
	removeContainer: function(index)
	{
		var opt = options.get();
		
		if (typeof index !== "number")
			index = opt.getContainerIndex(index);
		
		if (index < 0)
			return false;
		
		opt.containers.splice(index, 1);

		localStorage.options = JSON.stringify(opt);
		return result;
	},
};

var scripts =
{
	resizeContainers: function()
	{
		$(".container.small .area").each(ItemGroup.prototype.setContainerArea);
	},
	populateBookmarkTree: function(list)
	{
		chrome.bookmarks.getTree(function(rootNode)
		{
			scripts.populateBookmark(list, rootNode[0]);
		});
	},
	populateBookmark: function(list, node, prefix)
	{
		if (node.children && node.children.length > 0)
		{
			var actualPrefix;
			if (prefix)
				actualPrefix = prefix + " &raquo; ";
			else
				actualPrefix = "";
			
			if (node.title)
			{
				actualPrefix += node.title;
				var opt = document.createElement("option");
				opt.innerHTML = actualPrefix;
				opt.value = node.id;
				list.options.add(opt);
			}
			for (var i = 0; i < node.children.length; i++)
				scripts.populateBookmark(list, node.children[i], actualPrefix);
		}
	}
};

var textResources =
{
	"label_detect_install": "Installation complete!",
	"label_detect_upgrade": "Upgraded to a new version!"
};

var resources =
{
	render: function(group, item)
	{
		var items = resources.get(item);
		if (items instanceof Array)
		{
			for (var i = 0; i < items.length; i++)
			{
				group.renderItem(items[i]);
			}
		}
		else
		{
			group.renderItem(items);
		}
	},
	get: function(item)
	{
		var group = resources[item.specialType];
		var subGroup;
		if (group)
		{
			subGroup = group[item.specialTypeParam];
			if (subGroup)
				return subGroup;
		}
		else
		{
			resources[item.specialType] = {};
			group = resources[item.specialType];
		}
		
		switch (item.specialType)
		{
			case "systemCommand":
				subGroup = systemCommands[item.specialTypeParam];
				break;
			case "bookmarkFolder":
				chrome.bookmarks.getChildren(item.specialTypeParam, function (bookmarks) {
					var items = [];
					for (var i = 0; i < bookmarks.length; i++)
					{
						if (bookmarks[i].url)
							items.push(bookmarks[i]);
					}
					group[item.specialTypeParam] = items;
				});
				while (!group[item.specialTypeParam]);
				subGroup = group[item.specialTypeParam];
				break;
			case "app":
			case "appsWhere":
			case "appsExcept":
				chrome.management.getAll(function(ext)
				{
					var items = [];
					ext = ext.filter(function (a) {
						return (a.enabled && a.isApp);
					});
					
					for (var i = 0; i < ext.length; i++)
						items.push(ext[i]);
					
					group[item.specialTypeParam] = items;
				});
				while (!group[item.specialTypeParam]);
				subGroup = group[item.specialTypeParam];
				break;
			case "rawHtml":
				subGroup = item.specialTypeParam;
				break;
		}
		
		group[descriptor.specialTypeParam] = subGroup;
	}
};

$(window).load(scripts.resizeContainers);
$(window).resize(scripts.resizeContainers);

$(".springboard .container a.item")
.live("click", function(e)
{
	var newUrl = this.href;
	if (/^(chrome|about)\:/i.test(newUrl))
	{
		e.preventDefault();
		
		chrome.tabs.getCurrent(function (t) {
			chrome.tabs.update(t.id, {url: newUrl })
		});
	}
});



ItemGroup.prototype = new Array();
ItemGroup.prototype.constructor = ItemGroup;
function ItemGroup(parentContainer)
{
	this.parentContainer = parentContainer;
}
ItemGroup.prototype.data = function()
{
	var buffer = [];
	for (var i = 0; i < this.length; i++)
	{
		buffer.push(this[i]);
	}
	return buffer;
};
ItemGroup.prototype.setContainerArea = function()
{
	var containerArea = null;
	if (this instanceof jQuery)
		containerArea = this;
	else if (this instanceof HTMLElement || typeof this === "string")
		containerArea = $(this);
	else
		containerArea = $(this.parentContainer.domElement);
	
	if (containerArea.is(".container.small"))
		containerArea = containerArea.find(".area");
	else
		return;

	if (containerArea && containerArea.length === 0)
		return;
	
	var parentWidth = containerArea.parent().innerWidth();
	var childWidth = containerArea.find(".item").outerWidth(true);
	
	if (childWidth && childWidth > 0)
	{
		var areaWidth = parentWidth - (parentWidth % childWidth);
		containerArea.width(areaWidth);
	}
	else
	{
		setTimeout(function() {
			ItemGroup.prototype.setContainerArea.call(containerArea);
		}, 10);
	}
};
ItemGroup.prototype.renderGroup = function()
{
	var group = this;
	var designTime = group.parentContainer.domElement.closest(".designer").length > 0;
	var readOnly = group.parentContainer.domElement.is(".readOnly");
	for (var i = 0; i < this.length; i++)
	{
		var item = this[i];
		if (!item.specialType)
		{
			this.renderItem(item);
			continue;
		}
		switch (item.specialType)
		{
			case "systemCommand":
				this.renderItem(systemCommands[item.specialTypeParam]);
				break;
			case "bookmarkFolder":
				if (designTime)
				{
					group.renderMetaItem(item);
				}
				if (!designTime || readOnly)
				{
					chrome.bookmarks.getChildren(item.specialTypeParam, function (bookmarks) {
						for (var i = 0; i < bookmarks.length; i++)
						{
							if (bookmarks[i].url)
								group.renderItem(bookmarks[i]);
						}
					});
				}
				break;
			case "app":
			case "appsWhere":
			case "appsExcept":
				if (designTime)
				{
					group.renderMetaItem(item);
				}
				if (!designTime || readOnly)
				{	
					chrome.management.getAll(function(ext)
					{
						ext = ext.filter(function (a) {
							return (a.enabled && a.isApp);
						});
						
						for (var i = 0; i < ext.length; i++)
							group.renderItem(ext[i]);
					});
				}
				break;
			case "rawHtml":
				group.renderRawHtml(item.specialTypeParam);
				break;
		}
	}
};
ItemGroup.prototype.renderMetaItem = function(metaExt)
{
	var ext = { };
	ext.specialType = metaExt.specialType;
	ext.specialTypeParam = metaExt.specialTypeParam;
	
	switch (metaExt.specialType)
	{
		case "bookmarkFolder":
			ext.url = "chrome://bookmarks/#" + metaExt.specialTypeParam;
			ext.name = "All Items in Folder";
			ext.icons = [{"size": 48, "url": chrome.extension.getURL("themes/Faenza/fileset.png")}];
			break;
		case "appsWhere":
		case "appsExcept":
			ext.url = "chrome://extensions/#" + metaExt.specialType;
			if (metaExt.specialTypeParam)
				ext.url += "-" + metaExt.specialTypeParam;
			ext.name = "All Apps";
			ext.icons = [{"size": 48, "url": chrome.extension.getURL("themes/Faenza/fileset.png")}];
			break;
	}
	this.renderItem(ext);
};
ItemGroup.prototype.renderItem = function(ext)
{
	if (!ext.url)
	{
		if (ext.appLaunchUrl && ext.appLaunchUrl.length > 0)
			ext.url = ext.appLaunchUrl;
		else if (ext.optionsUrl && ext.optionsUrl.length > 0)
			ext.url = ext.optionsUrl;
		else
			ext.url = ext.homepageUrl;
	}
	if (!ext.name && ext.title)
		ext.name = ext.title;
	
	var item = $.tmpl("item", ext);
	item.data("object", ext);
	
	var icon = item.find(".icon");
	item.data("id", ext.id);
	item.appendTo($(this.parentContainer.domElement).find(".area"));
	item.data("object", ext);
	
	if (ext.isSystem)
		item.addClass("system");
		
	if (ext.icons && ext.icons.length > 0)
	{
		var iconUrl = this.getIcon(ext).url;
		if (!ext.enabled)
			iconUrl += "?grayscale=true";
		
		icon.css("background", "url('" + iconUrl + "') no-repeat");
		icon.css("backgroundSize", "cover");
	}
	else
	{
		icon.css("background", "url('chrome://favicon/" + ext.url + "') no-repeat");
		icon.css("backgroundSize", "cover");
	}
	
	if (!this.containerSet)
	{
		this.containerSet = true;
		this.setContainerArea();
	}
};
ItemGroup.prototype.renderRawHtml = function(rawHtml)
{
	var item = $.tmpl("rawHtml", html);
	item.appendTo(this.parentContainer.domElement);
};
ItemGroup.prototype.getIcon = function(ext)
{
	var bestFit = null;
	for (var i = 0; i < ext.icons.length; i++)
	{
		if (ext.icons[i].size == this.parentContainer.size)
			return ext.icons[i];
		else if (bestFit == null)
			bestFit = ext.icons[i];
		else if (ext.icons[i].size > bestFit.size && bestFit.size < this.parentContainer.size)
			bestFit = ext.icons[i];
		else if (ext.icons[i].size < bestFit.size && ext.icons[i].size > this.parentContainer.size)
			bestFit = ext.icons[i];
	}
	if (bestFit.url.indexOf(":") < 0)
		bestFit.url = chrome.extension.getURL(bestFit.url);
	return bestFit;
};

Container.prototype.constructor = Container;
function Container(title, size, classes, id)
{
	var created = false;
	
	if (arguments.length > 0)
	{
		if (typeof title === "string")
		{
			this.title = title;
			this.size = size;
			this.classes = classes || "";
			this.id = id;
		}
		else
		{
			this.title = title.title;
			this.size = title.size;
			this.classes = title.classes || "";
			this.id = title.id;
		}
	}
	
	this.showIcons = true;
	this.showLabels = true;
	
	this.items = new ItemGroup(this);
	this.domElement = null;
};
Container.prototype.create = function(parentElement)
{
	if (this.created) return;
	
	this.domElement = $.tmpl("container", this);
	
	if (this.classes)
		this.domElement.addClass(this.classes);
	
	if (this.size < 48)
		this.domElement.addClass("small");
	else if (this.size > 48)
		this.domElement.addClass("large");
		
	this.domElement.appendTo($(parentElement || document.body));
	$(this.domElement).data("object", this);
	
	this.created = true;
};
Container.prototype.data = function()
{
	var copy = { };
	copy.id = this.id;
	copy.title = this.title;
	copy.size = this.size;
	copy.classes = this.classes;
	copy.items = this.items.data();
	return copy;
};
Container.prototype.add = function(items, atIndex)
{
	var addedItems = [];
	var index;
	if (typeof atIndex === "number" && atIndex >= 0)
		index = atIndex;
	else
		index = this.items.length; 
	var args = [index, 0];
	
	if (items instanceof Array)
		addedItems = addedItems.concat(items);
	else
		addedItems.push(items);
	
	Array.prototype.splice.apply(this.items, args.concat(addedItems));
	
	if (!this.created)
		return;
	
	if (atIndex >= 0)
	{
		this.render();
	}
	else
	{
		for (var i = 0; i < addedItems.length; i++)
		{
			this.items.renderItem(addedItems[i]);
		}
	}
};
Container.prototype.remove = function(item)
{
	for (var i = 0; i < this.items.length; i++)
	{
		if (this.items[i].id === item.id)
		{
			this.items.splice(i, 1);
			i--;
		}
	}
	
	if (this.created)
	{
		this.render();
	}
};
Container.prototype.render = function(parentElement)
{
	this.create(parentElement);
	
	$(this.domElement).find(".area").empty();
	this.items.renderGroup();
};
